package com.hskn.hss.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageInfo;
import com.hskn.hss.core.page.TableDataInfo;
import com.hskn.hss.utils.page.PageVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import redis.clients.jedis.Jedis;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.BigDecimal;
import java.net.InetAddress;
import java.net.URL;
import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.YearMonth;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Slf4j
public class Tools {

    public static PageVo page(Long pageToPage, Long pageToSize, List list) {
        // 分页
        Long page = StringUtils.isEmpty(pageToPage) ? 1 : pageToPage;
        Long size = StringUtils.isEmpty(pageToSize) ? 10 : pageToSize;
        PageVo pageVo = new PageVo();

        pageVo.setTotal((long) list.size());
        pageVo.setCurrent(page);
        pageVo.setSize(size);
        BigDecimal pageSizeB = new BigDecimal(size);
        BigDecimal sizeB = new BigDecimal(list.size());
        pageVo.setPages(Long.valueOf(sizeB.divide(pageSizeB, BigDecimal.ROUND_CEILING).toString()));

        pageVo.setList(new ArrayList<>());
        for (int i = 0; i < list.size(); i++) {
            if (i >= size * (page - 1) && i < size * page) {
                pageVo.getList().add(list.get(i));
            }
        }
        return pageVo;
    }

    public static Integer getNum(String a) {
        String regEx = "[^0-9]";
        Pattern p = Pattern.compile(regEx);
        Matcher m = p.matcher(a);
        return Integer.valueOf(m.replaceAll("").trim());
    }

    /***
     * 获取 request 中 json 字符串的内容
     *
     * @param request
     * @return : <code>byte[]</code>
     * @throws IOException
     */
    public static String getRequestJsonString(HttpServletRequest request)
            throws IOException {
        String submitMehtod = request.getMethod();
        // GET
        if (submitMehtod.equals("GET")) {
            return new String(request.getQueryString().getBytes("iso-8859-1"), "utf-8").replaceAll("%22", "\"");
            // POST
        } else {
            return getRequestPostStr(request);
        }
    }

    /**
     * 描述:获取 post 请求内容
     * <pre>
     * 举例：
     * </pre>
     *
     * @param request
     * @return
     * @throws IOException
     */
    public static String getRequestPostStr(HttpServletRequest request)
            throws IOException {
        byte buffer[] = getRequestPostBytes(request);
        String charEncoding = request.getCharacterEncoding();
        if (charEncoding == null) {
            charEncoding = "UTF-8";
        }
        return new String(buffer, charEncoding);
    }

    /**
     * 描述:获取 post 请求的 byte[] 数组
     * <pre>
     * 举例：
     * </pre>
     *
     * @param request
     * @return
     * @throws IOException
     */
    public static byte[] getRequestPostBytes(HttpServletRequest request)
            throws IOException {
        int contentLength = request.getContentLength();
        if (contentLength < 0) {
            return null;
        }
        byte buffer[] = new byte[contentLength];
        for (int i = 0; i < contentLength; ) {

            int readlen = request.getInputStream().read(buffer, i,
                    contentLength - i);
            if (readlen == -1) {
                break;
            }
            i += readlen;
        }
        return buffer;
    }


    public static String getBody(HttpServletRequest request) {
        StringBuffer sb = new StringBuffer();
        InputStreamReader isr = null;
        char[] buf = null;
        try {
            int size = request.getContentLength();
            sb = new StringBuffer((int) (size * 1.2));
            request.setCharacterEncoding("UTF-8");
            isr = new InputStreamReader(request.getInputStream(), StandardCharsets.UTF_8);
            buf = new char[1024];
            int r;
            while ((r = isr.read(buf)) != -1) {
                sb.append(new String(buf, 0, r));
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            buf = null;
            if (isr != null) {
                try {
                    isr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return sb.toString();
    }

    /**
     * 通过ticket获取当前对应的用户
     *
     * @param ticket String
     * @return JSONObject
     */
    public static JSONObject getUser4Ticket(String ticket) {
        //解密
        JSONObject jsonUser = new JSONObject();
        if (StringUtils.isNotEmpty(ticket)) {
            byte[] decrptResultBytes = Base64.decodeBase64(ticket);
            byte[] decryptResult = AES.decrypt(decrptResultBytes, AES.AES_KEY);
            if (null != decryptResult) {
                jsonUser = JSONObject.parseObject(new String(decryptResult));
            }
        }
        return jsonUser;
    }

    /**
     * 获取当前HttpServletRequest对象
     *
     * @return HttpServletRequest
     */
    public static HttpServletRequest getCurrentHttpServletRequest() {
        return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
    }

    /**
     * 获取当前HttpServletResponse对象
     *
     * @return HttpServletResponse
     */
    public static HttpServletResponse getCurrentHttpServletResponse() {
        return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
    }

    /**
     * 把用户信息加密生成ticket
     *
     * @param content
     * @return
     */
    public static String createTicket(String content) {
        byte[] encryptResult = AES.encrypt(content, AES.AES_KEY);
        String ticket = Base64.encodeBase64URLSafeString(encryptResult);
        return ticket;
    }

    /**
     * 解析ticket为用户信息
     *
     * @param ticket
     * @return
     */
    public static JSONObject parseTicket(String ticket) {
        byte[] decrptResultBytes = Base64.decodeBase64(ticket);
        byte[] decryptResult = AES.decrypt(decrptResultBytes, AES.AES_KEY);
        JSONObject userInfo = JSON.parseObject(new String(decryptResult));
        return userInfo;
    }

    /**
     * 密码加密
     *
     * @param password
     * @param salt
     * @return
     */
    public static String encryptPassword(String password, String salt) {
        String res = null;
        if (StringUtils.isNotEmpty(password) && StringUtils.isNotEmpty(salt)) {
            res = MD5.getResult(BASE64.encryptBASE64(password + salt)).toUpperCase();
        }
        return res;
    }

    /**
     * get classloader from thread context if no classloader found in thread
     * context return the classloader which has loaded this class
     *
     * @return classloader
     */
    public static ClassLoader getCurrentClassLoader(Class c) {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        if (classLoader == null) {
            classLoader = c.getClassLoader();
        }
        return classLoader;
    }

    /**
     * 从classpath 加载配置信息
     *
     * @param configFileName 配置文件名称
     * @return 配置信息
     * @throws IOException
     */
    public static Properties loadFromClasspath(String configFileName, Class c) throws IOException {
        ClassLoader classLoader = getCurrentClassLoader(c);
        Properties config = new Properties();

        List<URL> properties = new ArrayList<URL>();
        Enumeration<URL> propertyResources = classLoader
                .getResources(configFileName);
        while (propertyResources.hasMoreElements()) {
            properties.add(propertyResources.nextElement());
        }

        for (URL url : properties) {
            InputStream is = null;
            try {
                is = url.openStream();
                config.load(is);
            } finally {
                if (is != null) {
                    is.close();
                    is = null;
                }
            }
        }
        return config;
    }

    /**
     * 获取客户端IP
     *
     * @param request HttpServletRequest
     * @return String
     */
    public static String getIpAddr(HttpServletRequest request) {
        String ip = null;
        ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0
                || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0
                || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0
                || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
            if (ip.equals("127.0.0.1")) {
                InetAddress inet = null;
                try {
                    inet = InetAddress.getLocalHost();
                } catch (UnknownHostException e) {
                    e.printStackTrace();
                }
                if (inet != null) {
                    ip = inet.getHostAddress();
                }
            }
        }
        if (ip.indexOf(",") > -1) {
            String[] e = ip.split(",");
            for (String string : e) {
                ip = string;
                break;
            }
        }
        return ip;
    }

    public static List<List<Object>> getBTable(List<List<Object>> results, List<BTable> list) {
        Boolean flag = true;
        for (int i = 0; i < results.size(); i++) {
            flag = true;
            for (int j = 0; j < list.size(); j++) {
                if (results.get(i).get(0).equals(list.get(j).getTime())) {
                    results.get(i).add(list.get(j).getData());
                    flag = false;
                    break;
                }
            }
            if (flag) {
                results.get(i).add(0);
            }

        }
        return results;
    }

    public static List<List<Object>> getBTable(List<BTable> bTableList) {
        List<List<Object>> resultList = new ArrayList<List<Object>>();
        List<Object> result = new ArrayList<Object>();
        for (BTable bTable : bTableList) {
            result.add(bTable.getTime());
            result.add(bTable.getData());
            resultList.add(result);
            result = new ArrayList<>();
        }
        return resultList;
    }

    /**
     * Date转YearMonth
     *
     * @param dbData
     * @return
     */
    public static YearMonth getMonthNumber(Date dbData) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(dbData);
        YearMonth yearMonth = YearMonth.of(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH) + 1);
        return yearMonth;
    }

    /**
     * 利用YearMonth方法compareTo比较两个时间相差几月
     */
    public static Integer getTweMonNum(Date endDate, Date startDate) {
        Integer difference = Tools.getMonthNumber(endDate).compareTo(Tools.getMonthNumber(startDate));
        return difference;
    }

    /**
     * 获取这个月有几周
     *
     * @param dbData
     * @return
     */
    public static Integer getMonthOfWeekNumber(Date dbData) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(dbData);
        return calendar.getActualMaximum(Calendar.WEEK_OF_MONTH);
    }

    /**
     * 两个时间相差几天
     *
     * @param
     * @return
     */
    public static Integer getTweDaysNumber(Date end, Date start) {
        int a = (int) ((end.getTime() - start.getTime()) / (1000 * 3600 * 24));
        return a;
    }

    /**
     * 一个时间加几天的Long值
     *
     * @param
     * @return
     */
    public static Long getDateAddDay(Date date, Integer f) {
        Long a = (date.getTime() + (1000 * 3600 * 24 * f));
        return a;
    }

    /**
     * 一个时间加几分钟的Long值
     *
     * @param
     * @return
     */
    public static Long getDateAddNumber(Date date, Integer f) {
        Long a = (date.getTime() + (1000 * 60 * f));
        return a;
    }

    /**
     * 获取两个时间段内的所有日期，日期可跨年
     *
     * @param
     * @return
     */
    public static List<String> getBetweenDate(String begin, String end) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        List<String> betweenList = new ArrayList<String>();

        try {
            Calendar startDay = Calendar.getInstance();
            startDay.setTime(format.parse(begin));
            startDay.add(Calendar.DATE, -1);

            while (true) {
                startDay.add(Calendar.DATE, 1);
                Date newDate = startDay.getTime();
                String newend = format.format(newDate);
                betweenList.add(newend);
                if (end.equals(newend)) {
                    break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return betweenList;
    }

    /**
     * 获取两个时间段内的所有年月，日期可跨年
     *
     * @param
     * @return
     */
    public static List<String> getBetweenMonth(String begin, String end) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM");
        List<String> betweenList = new ArrayList<String>();

        try {
            Calendar startDay = Calendar.getInstance();
            startDay.setTime(format.parse(begin));
            startDay.set(Calendar.DAY_OF_MONTH, 1);
            startDay.add(Calendar.MONTH, -1);
            Calendar endDay = Calendar.getInstance();
            endDay.setTime(format.parse(end));
            endDay.set(Calendar.DAY_OF_MONTH, 1);
            end = format.format(endDay.getTime());
            while (true) {
                startDay.add(Calendar.MONTH, 1);
                Date newDate = startDay.getTime();
                String newend = format.format(newDate);
                betweenList.add(newend);
                if (end.equals(newend)) {
                    break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return betweenList;
    }

    /**
     * 获取两个时间段内的所有日期，日期可跨年
     *
     * @param
     * @return
     */
    public static List<Date> getBetweenDateList(String begin, String end) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        List<Date> betweenList = new ArrayList<Date>();

        try {
            Calendar startDay = Calendar.getInstance();
            startDay.setTime(format.parse(begin));
            startDay.add(Calendar.DATE, -1);

            while (true) {
                startDay.add(Calendar.DATE, 1);
                Date newDate = startDay.getTime();
                betweenList.add(newDate);
                if (format.parse(end).getTime() <= newDate.getTime()) {
                    break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return betweenList;
    }

    /**
     * LocalDate 转 Date
     *
     * @param localDate
     * @return
     */
    public static Date localDate2Date(LocalDate localDate) {
        if (null == localDate) {
            return null;
        }
        ZonedDateTime zonedDateTime = localDate.atStartOfDay(ZoneId.systemDefault());
        return Date.from(zonedDateTime.toInstant());
    }

    /**
     * Date转String
     *
     * @param dbData
     * @return "yyyy-MM"格式
     */
    public static String getYearMonthString(Date dbData) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(dbData);
        YearMonth yearMonth = YearMonth.of(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH) + 1);
        String str = DateTimeFormatter.ofPattern("yyyy-MM").format(yearMonth);
        return str;
    }

    /**
     * Date转String
     *
     * @param dbData
     * @return "yyyy-MM-dd"格式
     */
    public static String getYearMonthDayString(Date dbData) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        return format.format(dbData);
    }


    /**
     * String转Date
     *
     * @param dbData
     * @return "yyyy-MM-dd"格式
     */
    public static Date getYearMonthDayDate(String dbData) throws ParseException {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        return format.parse(dbData);
    }

    /**
     * Date转String
     *
     * @param dbData
     * @return "yyyy-MM-dd HH:mm:ss"格式
     */
    public static String getDayString(Date dbData) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return format.format(dbData);
    }

    /**
     * 前七天的开始
     *
     * @param date
     * @return "yyyyMMddHHmmss"格式
     */
    public static Date getDateForBeginServenDay(Date date) {

        Calendar calendar = new GregorianCalendar();

        calendar.setTime(date);

        calendar.add(Calendar.DATE, -7);

        calendar.set(Calendar.HOUR_OF_DAY, 0);

        calendar.set(Calendar.MINUTE, 0);

        calendar.set(Calendar.SECOND, 0);

        calendar.set(Calendar.MILLISECOND, 0);

        Date date_start = calendar.getTime();
        return date_start;
    }

    /**
     * 后七天的开始
     *
     * @param date
     * @return "yyyyMMddHHmmss"格式
     */
    public static Date getDateForNextServenDay(Date date) {

        Calendar calendar = new GregorianCalendar();

        calendar.setTime(date);

        calendar.add(Calendar.DATE, 7);

        calendar.set(Calendar.HOUR_OF_DAY, 0);

        calendar.set(Calendar.MINUTE, 0);

        calendar.set(Calendar.SECOND, 0);

        calendar.set(Calendar.MILLISECOND, 0);

        Date date_start = calendar.getTime();
        return date_start;
    }

    /**
     * 一天的开始
     *
     * @param date
     * @return "yyyyMMddHHmmss"格式
     */
    public static Date getDateForBegin(Date date) {

        Calendar calendar = new GregorianCalendar();

        calendar.setTime(date);

        calendar.set(Calendar.HOUR_OF_DAY, 0);

        calendar.set(Calendar.MINUTE, 0);

        calendar.set(Calendar.SECOND, 0);

        calendar.set(Calendar.MILLISECOND, 0);

        Date date_start = calendar.getTime();
        return date_start;
    }

    /**
     * 一年的开始
     *
     * @param date
     * @return "yyyyMMddHHmmss"格式
     */
    public static Date getFirstDayOfYear(Date date) {

        Calendar calendar = new GregorianCalendar();

        calendar.setTime(date);
        calendar.set(Calendar.MONTH, 0);

        calendar.set(Calendar.DAY_OF_MONTH, 1);

        calendar.set(Calendar.HOUR_OF_DAY, 0);

        calendar.set(Calendar.MINUTE, 0);

        calendar.set(Calendar.SECOND, 0);

        calendar.set(Calendar.MILLISECOND, 0);

        Date date_start = calendar.getTime();
        return date_start;
    }

    /**
     * 一天的结束
     *
     * @param date
     * @return "yyyyMMddHHmmss"格式
     */
    public static Date getDateForEnd(Date date) {

        Calendar calendar_end = new GregorianCalendar();

        calendar_end.setTime(date);

        calendar_end.set(Calendar.HOUR_OF_DAY, 23);

        calendar_end.set(Calendar.MINUTE, 59);

        calendar_end.set(Calendar.SECOND, 59);

        calendar_end.set(Calendar.MILLISECOND, 999);

        Date date_end = calendar_end.getTime();
        return date_end;
    }

    /**
     * Date转String
     *
     * @param dbData
     * @return "yyyyMMddHHmmss"格式
     */
    public static String getDayStringForTime(Date dbData) {
        SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
        return format.format(dbData);
    }

    /**
     * 响应请求分页数据
     */
    @SuppressWarnings({"rawtypes", "unchecked"})
    public static TableDataInfo getDataTable(List<?> list) {
        TableDataInfo rspData = new TableDataInfo();
        rspData.setRows(list);
        rspData.setTotal(new PageInfo(list).getTotal());
        return rspData;
    }

    public static String getDateString(Date date) {
        String pattern = "yyyy-MM-dd HH:mm:ss";
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);
        return simpleDateFormat.format(date);
    }

    public static String reader(String filePath) {
        StringBuilder laststr = new StringBuilder();
        File file = new File(filePath);// 打开文件
        BufferedReader reader = null;
        try {
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
            reader = new BufferedReader(new InputStreamReader(bis, StandardCharsets.UTF_8), 10 * 1024 * 1024);// 读取文件
            String tempString = null;
            while ((tempString = reader.readLine()) != null) {
                laststr.append(tempString);
            }
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException el) {
                }
            }
        }
        return laststr.toString();
    }

    /**
     * java获取 当月所有的日期集合
     *
     * @return
     */
    public static List<String> getDayListOfMonth() {
        List list = new ArrayList();
        Calendar aCalendar = Calendar.getInstance(Locale.CHINA);
        int year = aCalendar.get(Calendar.YEAR);//年份
        int month = aCalendar.get(Calendar.MONTH) + 1;//月份
        int day = aCalendar.getActualMaximum(Calendar.DATE);
        String monthStr = "0";
        if (month < 10) {
            monthStr = "0" + month;
        } else {
            monthStr = String.valueOf(month);
        }
        for (int i = 1; i <= day; i++) {
            String days = "0";
            if (i < 10) {
                days = "0" + i;
            } else {
                days = String.valueOf(i);
            }
            String aDate = year + "-" + monthStr + "-" + days;
            SimpleDateFormat sp = new SimpleDateFormat("yyyy-MM-dd");
            try {
                Date date = sp.parse(aDate);
                list.add(aDate);
            } catch (ParseException e) {
                e.printStackTrace();
            }

        }
        return list;
    }

    /**
     * java获取 指定月所有的日期集合
     *
     * @return
     */
    public static List<String> getDayListOfMonthByDate(Date adate) {
        List list = new ArrayList();
        Calendar aCalendar = Calendar.getInstance(Locale.CHINA);
        aCalendar.setTime(adate);
        int year = aCalendar.get(Calendar.YEAR);//年份
        int month = aCalendar.get(Calendar.MONTH) + 1;//月份
        int day = aCalendar.getActualMaximum(Calendar.DATE);
        String monthStr = "0";
        if (month < 10) {
            monthStr = "0" + month;
        } else {
            monthStr = String.valueOf(month);
        }
        for (int i = 1; i <= day; i++) {
            String days = "0";
            if (i < 10) {
                days = "0" + i;
            } else {
                days = String.valueOf(i);
            }
            String aDate = year + "-" + monthStr + "-" + days;
            SimpleDateFormat sp = new SimpleDateFormat("yyyy-MM-dd");
            try {
                Date date = sp.parse(aDate);
                list.add(aDate);
            } catch (ParseException e) {
                e.printStackTrace();
            }

        }
        return list;
    }

    /**
     * 秒数化成时分秒
     *
     * @param second
     * @return
     */

    public static String secondToTime(long second) {
//        long days = second / 86400;//转换天数
//        second = second % 86400;//剩余秒数
        long hours = second / 3600;//转换小时数
        second = second % 3600;//剩余秒数
        long minutes = second / 60;//转换分钟
        second = second % 60;//剩余秒数
//        if (0 < days) {
//            return days + "天，" + hours + "小时，" + minutes + "分，" + second + "秒";
//        } else {
//            return hours + "小时" + minutes + "分钟" + second +"秒";
//        }
        if (hours > 0) {
            return hours + "小时" + minutes + "分钟" + second + "秒";
        } else if (minutes > 0) {
            return minutes + "分钟" + second + "秒";
        } else {
            return second + "秒";
        }
    }

    public static String getFristDay(Date date) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        //获取前月的第一天
        Calendar cal_1 = Calendar.getInstance();//获取当前日期
        cal_1.setTime(date);
        cal_1.set(Calendar.DAY_OF_MONTH, 1);//设置为1号,当前日期既为本月第一天
        String firstDay = format.format(cal_1.getTime());
        //System.out.println("-----1------firstDay:"+firstDay);
        return firstDay;
    }

    public static String getLastDay(Date date) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        //获取前月的第一天
        Calendar cal_2 = Calendar.getInstance();//获取当前日期
        cal_2.setTime(date);
        cal_2.add(Calendar.MONTH, 1);
        cal_2.set(Calendar.DAY_OF_MONTH, 0);//设置为1号,当前日期既为本月第一天
        String lastDay = format.format(cal_2.getTime());
        //System.out.println("-----1------firstDay:"+firstDay);
        return lastDay;
    }

    /**
     * 一月的开始
     *
     * @param date
     * @return java.util.Date
     * @author zcy
     * @date 2021/10/19 10:22
     */
    public static Date getFristDayForDate(Date date) {
        LocalDate localDate = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        localDate = LocalDate.of(localDate.getYear(), localDate.getMonth(), 1);
        ZonedDateTime zonedDateTime = localDate.atStartOfDay(ZoneId.systemDefault());
        LocalDate firstday = localDate.with(TemporalAdjusters.firstDayOfMonth());
        return Date.from(firstday.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * 一月的结束
     *
     * @param date
     * @return java.util.Date
     * @author zcy
     * @date 2021/10/19 10:22
     */
    public static Date getLastDayForDate(Date date) {
        Calendar calendar = new GregorianCalendar();

        calendar.setTime(date);
        calendar.add(Calendar.MONTH, 1);
        calendar.set(Calendar.DAY_OF_MONTH, 0);
        calendar.set(Calendar.HOUR_OF_DAY, 23);

        calendar.set(Calendar.MINUTE, 59);

        calendar.set(Calendar.SECOND, 59);

        calendar.set(Calendar.MILLISECOND, 999);

        return calendar.getTime();
    }

    public static void main(String[] args) {
        System.out.println(getLastDayForDate(new Date()));
    }

    public static List<String> getMonthList(String beginDateStr, String endDateStr) {
        SimpleDateFormat f = new SimpleDateFormat("yyyy-MM");
        //返回的月份列表
        List<String> sRet = new LinkedList<>();

        //定义一些变量
        Date beginDate = null;
        Date endDate = null;

        GregorianCalendar beginGC = null;
        GregorianCalendar endGC = null;

        try {
            //将字符串parse成日期
            beginDate = f.parse(beginDateStr);
            endDate = f.parse(endDateStr);

            //设置日历
            beginGC = new GregorianCalendar();
            beginGC.setTime(beginDate);

            endGC = new GregorianCalendar();
            endGC.setTime(endDate);

            //直到两个时间相同
            while (beginGC.getTime().compareTo(endGC.getTime()) <= 0) {
                //累加字符串,用单引号分隔
                if (sRet.equals("")) {
                    sRet.add(beginGC.get(Calendar.YEAR) + "-" + ((beginGC.get(Calendar.MONTH) + 1) > 9 ? (beginGC.get(Calendar.MONTH) + 1) : "0" + (beginGC.get(Calendar.MONTH) + 1)));
                } else {
                    sRet.add(beginGC.get(Calendar.YEAR) + "-" + ((beginGC.get(Calendar.MONTH) + 1) > 9 ? (beginGC.get(Calendar.MONTH) + 1) : "0" + (beginGC.get(Calendar.MONTH) + 1)));
                }

                //以月为单位，增加时间
                beginGC.add(Calendar.MONTH, 1);
            }
            return sRet;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public static Date getDateByString(String currentTime) throws ParseException {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
        Date dateString = formatter.parse(currentTime);
        return dateString;
    }

    /**
     * 获取当个对象
     */
    public static <T> T getBean(String str, Class<T> clazz) {
        Jedis jedis = null;
        try {
            T t = stringToBean(str, clazz);
            return t;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return null;
        }
    }

    private static <T> T stringToBean(String str, Class<T> clazz) {
        if (str == null || str.length() <= 0 || clazz == null) {
            return null;
        }
        if (clazz == int.class || clazz == Integer.class) {
            return (T) Integer.valueOf(str);
        } else if (clazz == String.class) {
            return (T) str;
        } else if (clazz == long.class || clazz == Long.class) {
            return (T) Long.valueOf(str);
        } else if (clazz == List.class) {
            return JSON.toJavaObject(JSON.parseArray(str), clazz);
        } else {
            return JSON.toJavaObject(JSON.parseObject(str), clazz);
        }
    }

    /**
     * 判断两个时间是否同一天
     *
     * @param date1
     * @param date2
     * @return boolean
     * @author zcy
     * @date 2021/10/7 9:56
     */
    public static boolean isSameDay(Date date1, Date date2) {
        if (date1 != null && date2 != null) {
            Calendar cal1 = Calendar.getInstance();
            cal1.setTime(date1);
            Calendar cal2 = Calendar.getInstance();
            cal2.setTime(date2);
            return isSameDay(cal1, cal2);
        } else {
            throw new IllegalArgumentException("The date must not be null");
        }
    }

    public static boolean isSameDay(Calendar cal1, Calendar cal2) {
        if (cal1 != null && cal2 != null) {
            return cal1.get(0) == cal2.get(0) && cal1.get(1) == cal2.get(1) && cal1.get(6) == cal2.get(6);
        } else {
            throw new IllegalArgumentException("The date must not be null");
        }
    }

    /**
     * 获取startDate 到 endDate 的日期字符串集合
     *
     * @param simpleDateFormat “yyyy-MM-dd”
     * @param startDate
     * @param endDate
     * @return java.util.List<java.lang.String>
     * @author zcy
     * @date 2021/10/9 15:21
     */
    public static List<String> getDateList(SimpleDateFormat simpleDateFormat, Date startDate, Date endDate) throws ParseException {
        List<String> dateList = new ArrayList<>();
        Date nowDate = new Date();
        if (startDate == null) {
            startDate = simpleDateFormat.parse(Tools.getFristDay(nowDate));
        }
        if (endDate == null) {
            endDate = simpleDateFormat.parse(Tools.getLastDay(nowDate));
        }
        if (startDate.getTime() < nowDate.getTime() && endDate.getTime() > nowDate.getTime()) {
            dateList = Tools.getBetweenDate(simpleDateFormat.format(startDate), simpleDateFormat.format(nowDate));
        } else {
            dateList = Tools.getBetweenDate(simpleDateFormat.format(startDate), simpleDateFormat.format(endDate));
        }
        return dateList;
    }

    /**
     * 获取startDate 到 endDate 的日期字符串集合
     *
     * @param simpleDateFormat “yyyy-MM”
     * @param startDate
     * @param endDate
     * @return java.util.List<java.lang.String>
     * @author zcy
     * @date 2021/10/9 15:21
     */
    public static List<String> getMonthList(SimpleDateFormat simpleDateFormat, Date startDate, Date endDate) throws ParseException {
        List<String> dateList = new ArrayList<>();
        Date nowDate = new Date();
        if (startDate == null) {
            startDate = simpleDateFormat.parse(Tools.getFristDay(nowDate));
        }
        if (endDate == null) {
            endDate = simpleDateFormat.parse(Tools.getLastDay(nowDate));
        }
        if (startDate.getTime() < nowDate.getTime() && endDate.getTime() > nowDate.getTime()) {
            dateList = Tools.getBetweenMonth(simpleDateFormat.format(startDate), simpleDateFormat.format(nowDate));
        } else {
            dateList = Tools.getBetweenMonth(simpleDateFormat.format(startDate), simpleDateFormat.format(endDate));
        }
        return dateList;
    }

    public static List<List<Object>> getDateEcharts(List<BTable> list, Date startDate, Date endDate) throws ParseException {
        List<List<Object>> results = new ArrayList<>();
        List<Object> res = new ArrayList<>();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        List<String> dateList = new ArrayList<>();
        dateList = Tools.getDateList(simpleDateFormat, startDate, endDate);
        for (String date : dateList) {
            res.add(date);
            results.add(res);
            res = new ArrayList<>();
        }
        return Tools.getBTable(results, list);
    }

    public static List<List<Object>> getMonthEcharts(List<BTable> list, Date startDate, Date endDate) throws ParseException {
        List<List<Object>> results = new ArrayList<>();
        List<Object> res = new ArrayList<>();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM");
        List<String> dateList = new ArrayList<>();
        dateList = Tools.getMonthList(simpleDateFormat, startDate, endDate);
        for (String date : dateList) {
            res.add(date);
            results.add(res);
            res = new ArrayList<>();
        }
        return Tools.getBTable(results, list);
    }

    public static TableDataInfo buildTableDataInfo(Integer page, Integer size, List<?> list) {
        if (Objects.isNull(list)) {
            return null;
        }
        TableDataInfo tableDataInfo = new TableDataInfo();
        PageInfoConvent pageInfoConvent = new PageInfoConvent(page, size, list);
        tableDataInfo.setRows(pageInfoConvent.getList());
        tableDataInfo.setTotal(list.size());
        return tableDataInfo;
    }

    /**
     * 校验时间格式
     *
     * @param str
     * @return
     */
    public static boolean isValidDate(String str) {
        boolean convertSuccess = true;
        // 指定日期格式为四位年/两位月份/两位日期，注意yyyy/MM/dd区分大小写；
        SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd HH:mm");
        try {
            // 设置lenient为false. 否则SimpleDateFormat会比较宽松地验证日期，比如2007/02/29会被接受，并转换成2007/03/01
            format.setLenient(false);
            format.parse(str);
        } catch (ParseException e) {
            // e.printStackTrace();
            // 如果throw java.text.ParseException或者NullPointerException，就说明格式不对
            convertSuccess = false;
        }
        return convertSuccess;
    }

    public static <T> List<T> castList(Object obj, Class<T> clazz) {
        List<T> result = new ArrayList<T>();
        if (obj instanceof List<?>) {
            for (Object o : (List<?>) obj) {
                result.add(clazz.cast(o));
            }
            return result;
        }
        return null;
    }

    public static <T> List<T> castJSONList(Object obj, Class<T> clazz) {
        List<T> result = new ArrayList<T>();
        if (obj instanceof List<?>) {
            for (Object o : (List<?>) obj) {
                result.add(clazz.cast(net.sf.json.JSONObject.fromObject(o)));
            }
            return result;
        }
        return null;
    }

    //校验时间格式
    public static boolean isDateTime(String datetime) {
        Pattern p = Pattern.compile("^((\\d{2}(([02468][048])|([13579][26]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])))))|(\\d{2}(([02468][1235679])|([13579][01345789]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|(1[0-9])|(2[0-8]))))))(\\s(((0?[0-9])|([1][0-9])|([2][0-4]))\\:([0-5]?[0-9])((\\s)|(\\:([0-5]?[0-9])))))?$");
        return p.matcher(datetime).matches();
    }

    //校验日期格式
    public static boolean isDate(String date) {
        Pattern p = Pattern.compile("^((\\d{2}(([02468][048])|([13579][26]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])))))|(\\d{2}(([02468][1235679])|([13579][01345789]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|(1[0-9])|(2[0-8]))))))?$");
        return p.matcher(date).matches();
    }

    /**
     * 类型转化
     *
     * @param <Target>
     * @return
     */
    public static final <Target> Target copyProperties(Object obj, Class<Target> clazz) {
        try {
            if (obj == null || clazz == null) {
                return null;
            }
            Target doInstance = clazz.newInstance();
            BeanUtils.copyProperties(obj, doInstance);
            return doInstance;
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return null;
    }


    public static HashMap<String, String> JsonObjectToHashMap(net.sf.json.JSONObject jsonObj) {
        HashMap<String, String> data = new HashMap<String, String>();
        Iterator it = jsonObj.keys();
        while (it.hasNext()) {
            String key = String.valueOf(it.next().toString());
            String value = jsonObj.get(key).toString();
            data.put(key, value);
        }
        System.out.println(data);
        return data;
    }

    /**
     * id包含计数器
     *
     * @param ids
     * @param ids2
     * @return
     */
    public static Integer idIncludeCounter(List<String> ids, List<String> ids2) {
        int num = 0;
        for (String id : ids) {
            if (ids2.contains(id)) {
                num++;
            }
        }
        return num;
    }
    /**
     * List拼串
     *
     * @param ids
     * @return
     */
    public static String stringSplicing(List<String> ids) {
        String str = "";
        if (CollectionUtils.isNotEmpty(ids)) {
            for (String id : ids) {
                str+= id+",";
            }
            str = str.substring(0,str.lastIndexOf(","));
            return str;
        }
        return "";
    }
}
